package com.foton.lotterydomain.activity.service.partake.imple;

import com.foton.dbrouterstarter.strategy.IDBRouterStrategy;
import com.foton.lotterycommon.common.Constants;
import com.foton.lotterycommon.common.Result;
import com.foton.lotterydomain.activity.model.req.PartakeReq;
import com.foton.lotterydomain.activity.model.vo.ActivityBillVO;
import com.foton.lotterydomain.activity.model.vo.DrawOrderVO;
import com.foton.lotterydomain.activity.model.vo.UserTakeActivityVO;
import com.foton.lotterydomain.activity.repository.IActivityRepository;
import com.foton.lotterydomain.activity.repository.IUserTakeActivityRepository;
import com.foton.lotterydomain.activity.service.partake.BaseActivityPartake;
import com.foton.lotterydomain.support.ids.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;

/**
 * @Author RenPu
 * @Date 2024/1/2 16:18
 * @Version 1.0
 * @Description:
 **/

@Slf4j
@Service
public class ActivityPartakeImpl extends BaseActivityPartake {


    @Resource
    private IActivityRepository activityRepository;

    @Resource
    private IDBRouterStrategy dbRouter;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private Map<Constants.Ids, IdGenerator> idGeneratorMap;

    @Resource
    private IUserTakeActivityRepository userTakeActivityRepository;



    @Override
    protected Result checkActivityBill(PartakeReq partake, ActivityBillVO bill) {
        // 校验：活动状态 (是否属于活动进行中的活动！！！！)
       if (!Constants.ActivityState.DOING.getCode().equals(bill.getState())){
           log.warn("活动当前状态非可用 state：{}", bill.getState());
           return Result.buildResult(Constants.ResponseCode.UN_ERROR.getCode(), "活动当前状态非可用");
       }

//        // 校验：活动日期 (活动开始时间在领取活动时间之后 或 活动结束时间在领取活动时间之前)
//        if (bill.getBeginDateTime().after(partake.getPartakeDate())||bill.getEndDateTime().before(partake.getPartakeDate())){
//            log.warn("活动时间范围非可用 beginDateTime：{} endDateTime：{}", bill.getBeginDateTime(), bill.getEndDateTime());
//            return Result.buildResult(Constants.ResponseCode.UN_ERROR.getCode(), "活动当前状态非可用");
//        }
//        Optional<Integer> optional = Optional.ofNullable(bill.getStockSurplusCount());
//        Integer anElse = optional.orElse(0);
        // 校验：活动库存
        if (0>=bill.getStockSurplusCount()){
            log.warn("活动剩余库存非可用 stockSurplusCount：{}", bill.getStockSurplusCount());
            return Result.buildResult(Constants.ResponseCode.UN_ERROR.getCode(), "活动当前状态非可用");
        }

        // 校验：个人库存 - 个人活动剩余可领取次数
        if (0>=bill.getUserTakeLeftCount()){
            log.warn("个人领取次数非可用 userTakeLeftCount：{}", bill.getUserTakeLeftCount());
            return Result.buildResult(Constants.ResponseCode.UN_ERROR.getCode(), "活动当前状态非可用");
        }

        return Result.buildSuccessResult();
    }

    @Override
    protected Result subtractionActivityStock(PartakeReq req) {
        int count=activityRepository.subtractionActivityStock(req);
        if(count==0){
            log.error("扣减活动库存失败 activityId：{}",req.getActivityId());
            return Result.buildResult(Constants.ResponseCode.UN_ERROR);
        }
        return Result.buildSuccessResult();
    }


    /**
     * 使用编码式事务，防止dbrouter进行数据源切换时，事务失败
     * @param partake 参与活动请求
     * @param bill    活动账单
     * @return
     */
    @Override
    protected Result grabActivity(PartakeReq partake, ActivityBillVO bill) {

        try{
            dbRouter.doRouter(String.valueOf(partake.getUserId()));
            return transactionTemplate.execute(status->{
                try {
                    // 根据活动ID值，进行扣减个人领取的次数
                    int updateCount = userTakeActivityRepository.subtractionLeftCount(bill.getActivityId(), bill.getActivityName(), bill.getTakeCount(), bill.getUserTakeLeftCount(), String.valueOf(partake.getUserId()), partake.getPartakeDate());
                    if(0==updateCount){
                        status.setRollbackOnly();  //回滚事务
                        log.error("领取活动，扣减个人已参与次数失败 activityId：{} uId：{}", partake.getActivityId(), partake.getUserId());
                        return Result.buildResult(Constants.ResponseCode.NO_UPDATE);
                    }

                    //保存领取记录
                    // 插入领取活动信息
                    Long takeId = idGeneratorMap.get(Constants.Ids.SnowFlake).nextId();
                    userTakeActivityRepository.takeActivity(bill.getActivityId(), bill.getActivityName(), bill.getTakeCount(), bill.getUserTakeLeftCount(), String.valueOf(partake.getUserId()), partake.getPartakeDate(), takeId);
                } catch (DuplicateKeyException e) {
                    status.setRollbackOnly();
                    log.error("领取活动，唯一索引冲突 activityId：{} uId：{}", partake.getActivityId(), partake.getUserId(), e);
                    return Result.buildResult(Constants.ResponseCode.INDEX_DUP);
                }
                return Result.buildSuccessResult();
            });
        }finally {
            dbRouter.clear();
        }

    }

    @Override
    protected UserTakeActivityVO queryNoConsumedTakeActivityOrder(Long activityId, String uId) {
        return userTakeActivityRepository.queryNoConsumedTakeActivityOrder(activityId,uId);
    }


    @Override
    public Result recordDrawOrder(DrawOrderVO drawOrder) {
        try{
            dbRouter.doRouter(String.valueOf(drawOrder.getuId()));
            return transactionTemplate.execute(status -> {
                try {
                    //尝试锁定活动领取记录
                    int lockTackActivity = userTakeActivityRepository.lockTackActivity(drawOrder.getuId(), drawOrder.getActivityId(), drawOrder.getTakeId());
                    if(0==lockTackActivity){
                        status.setRollbackOnly();
                        log.error("记录中奖单，个人参与活动抽奖已消耗完 activityId：{} uId：{}", drawOrder.getActivityId(), drawOrder.getuId());

                    }

                    //保存领取记录  保存抽奖信息
                    userTakeActivityRepository.saveUserStrategyExport(drawOrder);

                }catch (Exception e){
                    status.setRollbackOnly();
                }
               return Result.buildSuccessResult();
            });
        }finally {
            dbRouter.clear();
        }

    }

    @Override
    public void updateInvoiceMqState(String uId, Long orderId, Integer mqState) {
        userTakeActivityRepository.updateInvoiceMqState(uId, orderId, mqState);

    }
}
